<template>
  <common-edit-dialog
    :visible="dialogShow"
    :title="dialogTitle"
    :button-loading="loading"
    width="800px"
    @cancel="close('onlyClose')"
    @submit="submitForm"
  >
    <el-form
      ref="form"
      :model="form"
      :rules="rules"
      label-width="80px"
      @submit.native.prevent
    >
      <el-row :gutter="18">
        <el-col :span="12">
          <el-form-item label="角色名称" prop="roleName">
            <common-input
              v-model="form.roleName"
              :maxlength="16"
              :type="'text'"
              placeholder="请输入"
            />
          </el-form-item>
        </el-col>

        <el-col :span="12">
          <el-form-item label="角色编码" prop="roleKey">
            <common-input v-model="form.roleKey" placeholder="请输入" />
          </el-form-item>
        </el-col>

        <el-col :span="24">
          <el-form-item label="菜单权限" prop="forFrontMenuIdArr">
            <el-checkbox
              v-model="menuExpand"
              @change="handleCheckedTreeExpand($event, 'menu')"
              >展开/折叠</el-checkbox
            >
            <el-checkbox
              v-model="menuNodeAll"
              @change="handleCheckedTreeNodeAll($event, 'menu')"
              >全选/全不选</el-checkbox
            >
            <div class="form-box mt10">
              <el-tree
                class="tree-border"
                v-loading="treeLoading"
                :data="menuOptions"
                show-checkbox
                ref="menu"
                node-key="id"
                :default-checked-keys="form.forFrontMenuIdArr"
                :default-expanded-key="form.forFrontMenuIdArr"
                :check-strictly="checkStrictly"
                empty-text="暂无数据"
                @check-change="checkChange"
                :props="defaultProps"
              >
              </el-tree>
            </div>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="备注">
            <common-input
              type="textarea"
              :autosize="{ minRows: 4, maxRows: 8 }"
              v-model="form.remark"
              placeholder="请输入"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </common-edit-dialog>
</template>

<script>
import {
  roleInfo,
  role_add,
  role_edit,
  roleMenuTreeselect,
  menuTreeselect,
  getMenuTreeForRole,
} from "@/api/management/usercenter/user.js";
import { mapGetters } from "vuex";

export default {
  components: {},
  props: {},
  computed: {
    ...mapGetters(["roleIds"]),
  },
  data() {
    const checkContent = (rule, value, callback) => {
      if (value.length > 0 && this.form.forFrontMenuIdArr.length) {
        callback();
      } else {
        callback(new Error("请选择菜单"));
      }
    };
    return {
      checkStrictly: false,
      menuExpand: false,
      menuNodeAll: false,
      deptExpand: false,
      deptNodeAll: false,
      dataExpand: false,
      dataNodeAll: false,
      // dataSourceIds: [],
      dialogTitle: "新增", // 标题
      dialogShow: false, // 是否显示
      form: {
        status: "0",
        roleSort: "1",
        forFrontMenuIdArr: [],
      },
      rules: {
        roleName: [
          {
            required: true,
            message: "请输入角色名称",
            trigger: "blur",
          },
        ],
        roleKey: [
          {
            required: true,
            message: "请输入角色编码",
            trigger: "blur",
          },
          {
            required: true,
            // pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{2,20}$/,
            pattern: /^([\u4e00-\u9fa5]+|[a-zA-Z0-9_]+)$/,
            message: "只能输入大小写字母、数字、下划线",
            trigger: "blur",
          },
        ],
        forFrontMenuIdArr: [
          { required: true, validator: checkContent, trigger: "blur" },
        ],
      },
      dataSourceOptions: [],
      // 菜单列表
      menuOptions: [],
      //组织列表
      deptOptions: [],
      defaultProps: {
        children: "children",
        label: "label",
      },
      deptProps: {
        children: "children",
        label: "label",
      },
      dataSourceProp: {
        // 树参数
        children: "children",
        label: "name",
      },
      forFrontMenuIdArr: [], //前端需要进行勾选的key
      loading: false,
      treeLoading: false,
    };
  },
  methods: {
    // 树权限（展开/折叠）
    handleCheckedTreeExpand(value, type) {
      if (type == "menu") {
        let treeList = this.menuOptions;
        for (let i = 0; i < treeList.length; i++) {
          this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
        }
      } else if (type == "dataSource") {
        let treeList = this.dataSourceOptions;
        for (let i = 0; i < treeList.length; i++) {
          this.$refs.dataSource.store.nodesMap[treeList[i].id].expanded = value;
        }
      } else if (type == "dept") {
        let treeList = this.deptOptions;
        for (let i = 0; i < treeList.length; i++) {
          this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
        }
      }
    },
    // 树权限（全选/全不选）
    handleCheckedTreeNodeAll(value, type) {
      if (type == "menu") {
        this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
      } else if (type == "dataSource") {
        this.$refs.dataSource.setCheckedNodes(
          value ? this.dataSourceOptions : []
        );
      } else if (type == "dept") {
        this.setChecked(this.deptOptions, value);
      }
    },
    //遍历树  设置选中或不选中
    setChecked(data, value) {
      data.forEach((f) => {
        this.$refs.dept.setChecked(f, value);
        if (f.children && f.children.length) {
          this.setChecked(f.children, value);
        }
      });
      return data;
    },

    /** 根据角色ID查询菜单树结构 */
    getRoleMenuTreeselect(roleId) {
      return roleMenuTreeselect(roleId).then((response) => {
        this.menuOptions = response.menus;
        return response;
      });
    },
    /** 查询角色详情--编辑显示 */
    getRoleInfo(id) {
      roleInfo({ roleId: id }).then((res) => {
        if (res && res.code === 200) {
          this.form.menuIds = res.data.menuIds;
          this.form.forFrontMenuIdArr = res.data.forFrontMenuIdArr;
        } else {
          this.$GlobalErrorConfirm("获取信息失败", res.msg, "重新加载").then(
            () => {
              this.getRoleInfo(id);
            }
          );
        }
      });
    },
    /** 查询菜单树结构 */
    getMenuTreeselect(ids) {
      this.treeLoading = true;
      getMenuTreeForRole({ ids })
        .then((res) => {
          if (res && res.code === 200) {
            this.menuOptions = res.data;
          } else {
            this.menuOptions = [];
          }
        })

        .finally(() => (this.treeLoading = false));
    },
    checkChange(val, isTrue) {
      this.form.forFrontMenuIdArr = this.$refs.menu.getCheckedKeys(true);
    },
    /**
     * 关闭
     */
    close(onlyClose) {
      this.$refs.form.resetFields();
      this.dialogShow = false;
      this.resetOtherData();
      if (!onlyClose) {
        this.$emit("refresh");
      }
    },
    resetOtherData() {
      this.menuExpand = false;
      this.menuNodeAll = false;
      this.deptExpand = false;
      this.deptNodeAll = false;
      this.dataExpand = false;
      this.dataNodeAll = false;
      this.form.forFrontMenuIdArr = [];
      this.handleCheckedTreeNodeAll(false, "menu");
      this.handleCheckedTreeExpand(false, "menu");
    },
    /**
     * 显示
     */
    show(data) {
      this.dialogTitle = data.roleId ? "编辑角色" : "新增角色";
      this.dialogShow = true;
      this.form = data.roleId ? data : this.$options.data().form;
      this.getMenuTreeselect(
        data.roleId ? data.roleId : this.roleIds.join(",")
      );
      if (!!data.roleId) {
        this.getRoleInfo(data.roleId);
      }
    },
    // 所有菜单节点数据
    getMenuAllCheckedKeys() {
      // 目前被选中的菜单节点
      this.form.menuIds = this.$refs.menu.getCheckedKeys();
      let forFrontMenuIdArr = this.$refs.menu.getCheckedKeys();

      forFrontMenuIdArr.unshift.apply(forFrontMenuIdArr, halfCheckedKeys);
      this.forFrontMenuIdArr = forFrontMenuIdArr;
      return checkedKeys;
    },

    // 所有组织节点数据
    getDeptAllCheckedKeys() {
      // 目前被选中的菜单节点
      let checkedKeys = this.$refs.dept.getCheckedKeys();
      // 半选中的菜单节点
      let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
      return checkedKeys;
    },
    treeForeach(tree, func) {
      tree.forEach((data) => {
        data.children && this.treeForeach(data.children, func); // 遍历子树
        func(data);
      });
    },
    /**
     * 提交
     */
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          // 半选中的菜单节点
          let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
          let checkKeys = this.$refs.menu.getCheckedKeys();
          this.form.menuIds = [...checkKeys, ...halfCheckedKeys];
          this.loading = true;

          if (!!this.form.roleId) {
            role_edit(this.form)
              .then((res) => {
                if (res && res.code === 200) {
                  this.$GlobalSuccessMessage("编辑成功");
                  this.close();
                } else {
                  this.$GlobalErrorConfirm("编辑失败", res.msg);
                }
              })
              .finally(() => (this.loading = false));
          } else {
            role_add(this.form)
              .then((res) => {
                if (res && res.code === 200) {
                  this.$GlobalSuccessMessage("新增成功");
                  this.close();
                } else {
                  this.$GlobalErrorConfirm("新增失败", res.msg);
                }
              })
              .finally(() => (this.loading = false));
          }
        }
      });
    },

    /**
     * 获取指定树节点的全部路径
     * @param node 节点
     * @param path 返回路径
     */
    getNodeAllPath(node, path) {
      if (!path) path = [];

      if (node.parent) {
        path.unshift(node.data.label);
        this.getNodeAllPath(node.parent, path);
      }
      return path.join("/");
    },
  },
};
</script>
<style lang="scss" scoped>
.form-box {
  border: 1px solid #dcdfe6;
  padding: 15px;
  border-radius: 4px;
}
</style>
